package protocol

import (
	"encoding/json"
	"fmt"
	"hawkeye/common/logger"
)

// EventType 事件类型定义
type EventType int

const (
	EventHeartbeat EventType = iota + 1 // 心跳事件
	EventAuth                           // 认证事件
	EvenRegister
	EventCustom // 自定义事件起始值
)

// Message 消息结构
type Message struct {
	Event     EventType   `json:"event"`     // 事件编码
	Data      interface{} `json:"data"`      // 消息数据
	Timestamp int64       `json:"timestamp"` // 时间戳
	Sequence  uint64      `json:"sequence"`  // 消息序列号
}

// EncodeMessage 编码消息为字节流
func EncodeMessage(msg *Message) ([]byte, error) {
	// 先序列化JSON
	jsonData, err := json.Marshal(msg)
	if err != nil {
		return nil, fmt.Errorf("marshal message error: %v", err)
	}

	// 添加长度头
	length := len(jsonData)
	header := make([]byte, 4)
	header[0] = byte(length >> 24)
	header[1] = byte(length >> 16)
	header[2] = byte(length >> 8)
	header[3] = byte(length)

	// 组合消息
	fullMessage := make([]byte, 4+length)
	copy(fullMessage[0:4], header)
	copy(fullMessage[4:], jsonData)

	return fullMessage, nil
}

// DecodeMessage 从字节流解码消息
func DecodeMessage(data []byte) (*Message, error) {
	if len(data) < 4 {
		return nil, fmt.Errorf("message too short")
	}

	// 解析长度头（使用无符号整数避免负数）
	length := uint32(data[0])<<24 | uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3])

	// 检查长度是否合理
	if length == 0 || length > 10*1024*1024 { // 限制最大10MB
		return nil, fmt.Errorf("invalid message length: %d", length)
	}

	if len(data) < 4+int(length) {
		return nil, fmt.Errorf("incomplete message: expected %d bytes, got %d", 4+length, len(data))
	}

	// 解析JSON数据
	var msg Message
	err := json.Unmarshal(data[4:4+length], &msg)
	if err != nil {
		return nil, fmt.Errorf("unmarshal message error: %v", err)
	}

	return &msg, nil
}

func Convert[T any](data interface{}, dateType T) (*T, error) {
	// 如果是map，转换为JSON再解析
	if dataMap, ok := data.(map[string]interface{}); ok {
		jsonData, err := json.Marshal(dataMap)
		if err != nil {
			return nil, err
		}
		err = json.Unmarshal(jsonData, &dateType)
		logger.Info("Recv data:", dataMap)
		return &dateType, err
	}

	return nil, fmt.Errorf("invalid data type")
}
